
package com.dkm.modules.wx.order.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dkm.commons.Response;
import com.dkm.constant.Constant;
import com.dkm.dataScope.DataScope;
import com.dkm.modules.sys.operator.model.OperatorRoyaltyRecord;
import com.dkm.modules.sys.user.model.CustomerBalance;
import com.dkm.modules.sys.user.model.User;
import com.dkm.modules.wx.card.mapper.CardMapper;
import com.dkm.modules.wx.card.mapper.RechargeRecodMapper;
import com.dkm.modules.wx.card.model.Card;
import com.dkm.modules.wx.card.model.RechargeRecodPO;
import com.dkm.modules.wx.cashrecord.model.OperatorBalance;
import com.dkm.modules.wx.city.mapper.PlotMapper;
import com.dkm.modules.wx.order.mapper.OrderMapper;
import com.dkm.modules.wx.order.model.*;
import com.dkm.modules.wx.order.service.OrderService;
import com.dkm.modules.wx.pile.mapper.PileMapper;
import com.dkm.modules.wx.port.model.ChargingPort;
import com.dkm.util.IdGen;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName ChargingOrderServiceImpl
 * @Description: 订单实现类
 * @Author yangbin
 * @Date 2019-09-09 23:38
 * @Version V1.0
 **/
@Service
public class OrderServiceImpl implements OrderService  {

        private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);

        @Autowired
        private OrderMapper chargingOrderMapper;

        @Autowired
        private PileMapper pileMapper;

        @Autowired
        private PlotMapper plotMapper;

        @Autowired
        private CardMapper cardMapper;

        @Autowired
        private RechargeRecodMapper rechargeRecodMapper;

        @Override
        /**
         *@描述   获取订单列表（分页）
         *@参数  [page, orderQueryForm 查询参数]
         *@返回值  com.baomidou.mybatisplus.core.metadata.IPage<java.util.Map<java.lang.String,java.lang.Object>>
         *@创建人  yangbin
         *@创建时间  2019/10/5
         */
        @DataScope(alias = "d.userid")
        public IPage<OrderResult> getOrderList(Map<String,Object> params,Page<OrderResult> page) {
                List<OrderResult> orderList= chargingOrderMapper.getOrderList(params,page);
                return page.setRecords(orderList);
        }


        /**
         *@描述   通过用户名获取代理商首页数据
         *@参数  [userId 用户名]
         *@返回值  java.util.Map<java.lang.String,java.lang.Object>
         *@创建人  yangbin
         *@创建时间  2019/10/13
         * @param userId
         */
        @Override
        public Map<String, Object> getOperateData(Integer userId) {
                return chargingOrderMapper.getOperateData(userId);

        }


        /**
         *@描述   地址统计
         *@参数  [params 查询参数]
         *@返回值  java.util.List<com.dkm.modules.wx.order.model.AddressReport>
         *@创建人  yangbin
         *@创建时间  2019/10/13
         */
        @Override
        public List<AddressReport> getAddressStatistics(Map<String,Object> params) {
                List<AddressReport> datas= chargingOrderMapper.getAddressStatistics(params);
                return datas;
        }



        /**
         *@描述   今日收益
         *@参数  [orderQueryForm 查询参数]
         *@返回值  java.util.Map<java.lang.String,java.lang.Object>
         *@创建人  yangbin
         *@创建时间  2019/10/13
         */
        @Override
        public Map<String, Object> getDayProfit(OrderQueryForm orderQueryForm) {
                return chargingOrderMapper.getDayProfit(orderQueryForm);
        }


        /**
         *@描述   月收益
         *@参数  [userId 用户ID]
         *@返回值  java.util.Map<java.lang.String,java.lang.Object>
         *@创建人  yangbin
         *@创建时间  2019/10/13
         */
        @Override
        public MonProfit getMonProfit(Integer userId) {
                MonProfit monProfit = chargingOrderMapper.getMonProfit(userId);
                /*查询本月卡收益详情的数据*/
                List<Profit> profits = chargingOrderMapper.getProfits(userId);
                monProfit.setProfits(profits);
                return monProfit;
        }


        /**
         *@描述   查询订单详情
         *@参数  [orderNumber 订单编号]
         *@返回值  com.dkm.modules.wx.order.model.OrderResult
         *@创建人  yangbin
         *@创建时间  2019/10/5
         */
        @Override
        public OrderResult getOrderDetail(String orderNumber) {
                return chargingOrderMapper.getOrderDetail(orderNumber);
        }

        @Transactional
        @Override
        public Response<String> refundOrder(Integer orderId, User user, BigDecimal refundAmount) {

                if(null == orderId || null==refundAmount){
                    return Response.error(Constant.SUCCESS_CODE,-8,"订单id和退款金额不能为空！",null);
                }
                // 退款金额不能小于等于0
                if(refundAmount.compareTo(BigDecimal.ZERO)<=0){
                    return Response.error(Constant.SUCCESS_CODE,-9,"退款金额不能小于等于0！",null);
                }
                // 根据订单id查询订单信息
                OrderResult order =  chargingOrderMapper.getOrderDetailById(orderId);
                // 1.0 验证订单是否为空
                if(null == order){
                        return Response.error(Constant.SUCCESS_CODE,-10,"订单不存在！",null);
                }
                String orderState = order.getOrderstate();
                // 1.1 验证订单状态是否为已支付
                if(!Constant.ORDER_STATUS_HAS_PAYED.equals(orderState)){
                        return Response.error(Constant.SUCCESS_CODE,-11,"只有支付成功的订单可以退款！",null);
                }
                // 订单是否收费
                String orderFee = order.getIsFee();
                // 1.2 免费订单不可退款
                if(Constant.ORDER_IS_FREE.equals(orderFee)){
                    return Response.error(Constant.SUCCESS_CODE,-12,"免费订单不可退款！",null);
                }
                // 订单金额
                BigDecimal orderGold = new BigDecimal(order.getOrderGold());
                // 1.3 退款金额不能大于订单金额
                if(refundAmount.compareTo(orderGold)>0){
                    return Response.error(Constant.SUCCESS_CODE,-13,"退款金额不能大于订单金额！",null);
                }
                // 微信openId
                String openId = order.getOpenId();
                // 2.0 把订单金额充值到对应账号或者卡号上
                String cardNo = order.getCardNo();
                // 充值记录类型
                Integer  dataType = Constant.RECHARGE_RECOD_DATA_TYPE_ACCOUNT;
                // 卡id
                Integer cardId = null;
                Card card = new Card();
                // 如果卡号不为空，查询卡信息
                if(StringUtils.isNotBlank(cardNo)){
                    dataType = Constant.RECHARGE_RECOD_DATA_TYPE_CARD;
                    card = cardMapper.getCardInfo(cardNo);
                    cardId = card.getId();
                }
                // 充值记录
                RechargeRecodPO recodPO = RechargeRecodPO.builder()
                        .openId("")
                        .cardId(cardId)
                        .type(Constant.RECHARGE_RECOD_TYPE_ORDER_REFUND)
                        .dataType(dataType)
                        .quantity(refundAmount)
                        .rechargeNumber(order.getOrdernumber() + IdGen.uuid())
                        .status(1)
                        .openId(openId)
                        .createBy(user.getId())
                        .createTime(new Date())
                        .build();
                // 插入充值记录
                rechargeRecodMapper.insert(recodPO);
                // 充值金额到账户或者卡
                if(StringUtils.isNotBlank(cardNo)){
                    // 充值到卡
                    BigDecimal sum = card.getSum();
                    card.setSum(sum.add(refundAmount));
                    cardMapper.updateCardBalance(card);
                 // 充值到余额
                }else{
                    CustomerBalance balance = chargingOrderMapper.queryUserBalance(openId);
                    if(null == balance){
                        balance = new CustomerBalance();
                        balance.setAmount(refundAmount);
                        balance.setVersion(1);
                        balance.setOpenId(openId);
                        chargingOrderMapper.insertUserBalance(balance);
                    }else{
                        BigDecimal amount = balance.getAmount();
                        balance.setAmount(amount.add(refundAmount));
                        chargingOrderMapper.updateUserBalance(balance);
                    }
                }
                // 3.0 更新订单状态为已退款
                order.setOrderstate(Constant.ORDER_STATUS_HAS_REFUNDED);
                order.setRefundAmount(refundAmount);
                chargingOrderMapper.updateOrderRefundStatus(order);
                // 4.0 扣除对应代理商的费用
                String parkId = order.getParkId();
                // 根据充电桩id查询代理商余额表
                OperatorBalance operatorBalance = chargingOrderMapper.queryOperatorBalance(parkId);
                if(null != operatorBalance && null !=operatorBalance.getAmount()){
                    // 4.1 根据代理商分成，计算退款金额
                    // 查询代理商分成记录
                    OperatorRoyaltyRecord operatorRoyaltyRecord = new OperatorRoyaltyRecord();
                    operatorRoyaltyRecord.setOrderId(orderId.toString());
                    // 查询分成记录，如果分成记录为空，则不扣代理商的费用
                    operatorRoyaltyRecord = chargingOrderMapper.queryOperatorRoyaltyRecord(operatorRoyaltyRecord);
                    // 只有查询分成记录不为空，才会扣代理商的款
                    if(null!=operatorRoyaltyRecord){
                        // 该笔订单分成比例
                        BigDecimal royaltyPercent = operatorRoyaltyRecord.getRoyaltyPercent();
                        // 分成退款金额
                        BigDecimal royaltyAmount = refundAmount.multiply(royaltyPercent).divide(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP);
                        // 代理商余额
                        Float amount = operatorBalance.getAmount();
                        // 代理商余额减去退款金额
                        amount = amount - royaltyAmount.floatValue();
                        operatorBalance.setAmount(amount);
                        chargingOrderMapper.updateOperatorBalance(operatorBalance);
                        // 4.2 插入分成退款记录
                        operatorRoyaltyRecord.setRoyaltyAmount(royaltyAmount.negate());
                        chargingOrderMapper.insertOperatorRoyaltyRecord(operatorRoyaltyRecord);
                    }

                }

                return Response.ok(Constant.SUCCESS_CODE,0,"退款成功！",null);
        }



    /***
     * 订单记录可以更改这条记录对应的端口号和充电桩号
     * 场景是当某个充电桩扫描以后发现该充电桩出现故障呢，此时运营人员手动切换端口和桩号，有一定风险指数
     * 1.更改订单 端口和桩号
     * 2.将原订单的端口改成故障状态F
     * 3.将下发表数据更新成重新下发状态，更新新的桩号和端口
     */
    @Transactional
    public Response<String> portChange(String orderId, User userInfo, String portCode, String parkId) {
        // 查询新的端口和桩号是否存在，同时有没有被占用
        Map<String,Object> params = new HashMap<>();
        params.put("parkId",parkId);
        params.put("portCode",portCode);
        ChargingPort chargingPort = chargingOrderMapper.queryPortInfo(params);
        if(chargingPort!=null){
            String state = chargingPort.getState();
            if(Constant.PORT_STATE_F.equals(state) || Constant.PORT_STATE_Y.equals(state)){
                return Response.error(Constant.SUCCESS_CODE,-2,"充电桩占用或故障",null);
            }else {

                // 2.将原订单的端口改成故障状态F
                OrderResult orderResult =  chargingOrderMapper.getOrderDetailById(Integer.parseInt(orderId));
                String parklockId = orderResult.getParklockId();
                chargingOrderMapper.updatePortState(parklockId);

                // 将新的端口更改成使用状态
                Map<String,String> useStateMap = new HashMap<>();
                useStateMap.put("parkId",parkId);
                useStateMap.put("portCode",portCode);
                chargingOrderMapper.portChangedToUse(useStateMap);

                // 1.更改订单 端口和桩号
                Map<String,Object> orderParams = new HashMap<>();
                orderParams.put("orderId",orderId);
                orderParams.put("parklockid",chargingPort.getId());
                orderParams.put("parkid",chargingPort.getParkid());

                chargingOrderMapper.updateOrderParkCodeAndPortCode(orderParams);
                // 3.将下发表数据更新成重新下发状态，更新新的桩号和端口
                String orderNumber = orderResult.getOrdernumber();
                params.put("orderNumber",orderNumber);
                params.put("portCode",portCode);// 端口号
                params.put("parkId",parkId);// 充电桩编号
                chargingOrderMapper.updateDownload(params);


                return Response.ok(Constant.SUCCESS_CODE,0,"变更成功",null);



            }
        }else {
            return Response.error(Constant.SUCCESS_CODE,-1,"充电桩或端口不存在",null);
        }
    }

}
